/*
* Copyright (C) 2005-2009 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC Remote; see the file license. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
package org.xbmc.android.remote.presentation.controller;
import org.xbmc.android.remote.business.ManagerFactory;
import org.xbmc.android.remote.business.NowPlayingPollerThread;
import org.xbmc.android.remote.presentation.activity.NowPlayingActivity;
import org.xbmc.android.remote.presentation.activity.PlaylistActivity;
import org.xbmc.android.util.ConnectionFactory;
import org.xbmc.api.business.DataResponse;
import org.xbmc.api.business.IControlManager;
import org.xbmc.api.business.IEventClientManager;
import org.xbmc.api.data.IControlClient.ICurrentlyPlaying;
import org.xbmc.api.info.PlayStatus;
import org.xbmc.api.presentation.INotifiableController;
import org.xbmc.api.type.MediaType;
import org.xbmc.api.type.SeekType;
import org.xbmc.eventclient.ButtonCodes;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class NowPlayingController extends AbstractController implements INotifiableController, IController, Callback {
private static final String TAG = "NowPlayingController";
private IControlManager mControlManager;
private NowPlayingActivity mNowPlayingActivity;
private Handler mNowPlayingHandler;
private IEventClientManager mEventClientManager;
private int mPlayStatus = PlayStatus.UNKNOWN;
private int mPlayListId = -1;
private int mLastPosition = -1;
public NowPlayingController(NowPlayingActivity activity, Handler handler) {
super.onCreate(activity, handler);
mNowPlayingActivity = activity;
mControlManager = ManagerFactory.getControlManager(this);
mEventClientManager = ManagerFactory.getEventClientManager(this);
mNowPlayingHandler = new Handler(this);
}
/**
* This is called from the thread with a message containing updated
* info of what's currently playing.
* @param msg Message object containing currently playing info
*/
public synchronized boolean handleMessage(Message msg) {
final Bundle data = msg.getData();
final ICurrentlyPlaying currentlyPlaying = (ICurrentlyPlaying)data.getSerializable(NowPlayingPollerThread.BUNDLE_CURRENTLY_PLAYING);
switch (msg.what) {
case NowPlayingPollerThread.MESSAGE_PROGRESS_CHANGED:
mPlayStatus = currentlyPlaying.getPlayStatus();
mNowPlayingActivity.setProgressPosition(Math.round(currentlyPlaying.getPercentage()));
if (mPlayStatus == PlayStatus.PAUSED || mPlayStatus == PlayStatus.PLAYING) {
mNowPlayingActivity.updateProgress(currentlyPlaying.getDuration(), currentlyPlaying.getTime(), (mPlayStatus == PlayStatus.PAUSED));
} else {
mNowPlayingActivity.clear();
}
return true;
case NowPlayingPollerThread.MESSAGE_PLAYLIST_ITEM_CHANGED:
mNowPlayingActivity.updateInfo(currentlyPlaying.getTitle(), currentlyPlaying.getArtist(), currentlyPlaying.getAlbum());
mLastPosition = data.getInt(NowPlayingPollerThread.BUNDLE_LAST_PLAYPOSITION);
return true;
case NowPlayingPollerThread.MESSAGE_PLAYSTATE_CHANGED:
mPlayListId = data.getInt(NowPlayingPollerThread.BUNDLE_LAST_PLAYLIST);
return true;
case NowPlayingPollerThread.MESSAGE_COVER_CHANGED:
// TODO: FIX!!
mNowPlayingActivity.updateCover(ConnectionFactory.getNowPlayingPoller(mActivity).getNowPlayingCover(), (currentlyPlaying != null) ? currentlyPlaying.getMediaType() : MediaType.UNKNOWN);
return true;
case NowPlayingPollerThread.MESSAGE_CONNECTION_ERROR:
mPlayStatus = PlayStatus.UNKNOWN;
Log.w(TAG,"Received connection error from poller!");
return true;
case NowPlayingPollerThread.MESSAGE_RECONFIGURE:
mPlayStatus = PlayStatus.UNKNOWN;
new Thread(){
public void run(){
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
ConnectionFactory.subscribeNowPlayingPollerThread(mActivity.getApplicationContext(), mNowPlayingHandler);
}
}.start();
return true;
default:
return false;
}
}
public void enableSeekbar(SeekBar seekbar) {
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser && !seekBar.isInTouchMode())
seek(progress);
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
seek(seekBar.getProgress());
}
});
}
public void disableSeekbar(SeekBar seekbar) {
seekbar.setOnSeekBarChangeListener(null);
}
public void setupButtons(SeekBar seekbar, View prev, View stop, View playpause, View next, View playlist) {
enableSeekbar(seekbar);
// setup buttons
prev.setOnClickListener(new OnRemoteAction(ButtonCodes.REMOTE_SKIP_MINUS));
stop.setOnClickListener(new OnRemoteAction(ButtonCodes.REMOTE_STOP));
next.setOnClickListener(new OnRemoteAction(ButtonCodes.REMOTE_SKIP_PLUS));
playpause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
switch (mPlayStatus) {
case PlayStatus.PLAYING:
mEventClientManager.sendButton("R1", ButtonCodes.REMOTE_PAUSE, false, true, true, (short)0, (byte)0);
break;
case PlayStatus.PAUSED:
mEventClientManager.sendButton("R1", ButtonCodes.REMOTE_PLAY, false, true, true, (short)0, (byte)0);
break;
case PlayStatus.STOPPED:
final DataResponse<Boolean> doNothing = new DataResponse<Boolean>();
//mControlManager.setPlaylistId(doNothing, mPlayListId < 0 ? 0 : mPlayListId, mActivity.getApplicationContext());
mControlManager.setPlaylistPos(doNothing, mPlayListId < 0 ? 0 : mPlayListId, mLastPosition < 0 ? 0 : mLastPosition, mActivity.getApplicationContext());
break;
}
}
});
// playlist button
playlist.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mActivity.startActivity(new Intent(mActivity, PlaylistActivity.class));
}
});
}
public void seek(int progress) {
mControlManager.seek(new DataResponse<Boolean>(), SeekType.absolute, progress, mActivity.getApplicationContext());
}
/**
* Handles the push- release button code. Switches image of the pressed
* button, vibrates and executes command.
*/
private class OnRemoteAction implements OnClickListener {
private final String mAction;
public OnRemoteAction(String action) {
mAction = action;
}
public void onClick(View v) {
mEventClientManager.sendButton("R1", mAction, false, true, true, (short)0, (byte)0);
}
}
public void onActivityPause() {
ConnectionFactory.unSubscribeNowPlayingPollerThread(mActivity.getApplicationContext(), mNowPlayingHandler, true);
if (mControlManager != null) {
mControlManager.setController(null);
}
super.onActivityPause();
}
public void onActivityResume(final Activity activity) {
super.onActivityResume(activity);
new Thread("nowplaying-spawning") {
@Override
public void run() {
ConnectionFactory.subscribeNowPlayingPollerThread(activity.getApplicationContext(), mNowPlayingHandler);
}
}.start();
if (mControlManager != null) {
mControlManager.setController(this);
}
}
}